package com.franklin.java.api.spring.annotation.bean;

import com.franklin.java.api.annotation.BaseAnnotation;
import com.franklin.java.utils.PsiUtils;
import com.franklin.plugins.common.utils.StringHelper;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiType;
import org.apache.commons.lang.ArrayUtils;

import java.util.Objects;

/**
 * @author Franklin
 * @since 2021/8/13 16:48
 */
public class DependencyInjectionAnnotations extends BeanAnnotations {

    static {
        annotationMap.put(new Autowired());
        annotationMap.put(new Resource());
        annotationMap.put(new Qualifier());
        annotationMap.put(new ApacheDubboReference());
        annotationMap.put(new AlibabaDubboReference());
    }

    protected DependencyInjectionAnnotations() {
        super();
    }

    public static DependencyInjectionAnnotation parse(PsiAnnotation[] psiAnnotations, PsiType psiType){
        if (ArrayUtils.isEmpty(psiAnnotations)){
            return null;
        }

        PsiAnnotation autowiredAnn = null;
        PsiAnnotation resourceAnn = null;
        PsiAnnotation qualifierAnn = null;
        PsiAnnotation referenceAnn = null;
        DependencyInjectionAnnotation ann = null;
        for (PsiAnnotation psiAnnotation : psiAnnotations) {
            ann = BaseAnnotation
                .parse(psiAnnotation, DependencyInjectionAnnotation.class);
            if (ann instanceof Autowired){
                autowiredAnn = psiAnnotation;
            }else if (ann instanceof Resource){
                resourceAnn = psiAnnotation;
            }else if (ann instanceof Qualifier){
                qualifierAnn = psiAnnotation;
            }else if (ann instanceof ApacheDubboReference || ann instanceof AlibabaDubboReference){
                referenceAnn = psiAnnotation;
            }
        }
        String injectBeanName = "";

        String defaultBeanName = "";
        if (Objects.nonNull(psiType)){
            defaultBeanName = StringHelper.firstToLowerCase(psiType.getPresentableText());
        }

        if (Objects.nonNull(autowiredAnn)){
            //默认类型注入
            ann = BaseAnnotation.parse(autowiredAnn, DependencyInjectionAnnotation.class);
            if (Objects.isNull(qualifierAnn)){
                injectBeanName = getBeanName(autowiredAnn,"value",defaultBeanName);
            }else {
                injectBeanName = getBeanName(qualifierAnn,"value", defaultBeanName);
            }
        }else if (Objects.nonNull(resourceAnn)){
            //resource注入
            ann = BaseAnnotation.parse(resourceAnn, DependencyInjectionAnnotation.class);
            if (Objects.isNull(qualifierAnn)){
                injectBeanName = getBeanName(resourceAnn,"name", defaultBeanName);
            }else {
                injectBeanName = getBeanName(qualifierAnn,"value", defaultBeanName);
            }
        }else if (Objects.nonNull(qualifierAnn)){
            ann = BaseAnnotation.parse(qualifierAnn, DependencyInjectionAnnotation.class);
            injectBeanName = getBeanName(qualifierAnn,"value", defaultBeanName);
        }else if (Objects.nonNull(referenceAnn)){
            ann = BaseAnnotation.parse(referenceAnn,DependencyInjectionAnnotation.class);
            injectBeanName = getBeanName(referenceAnn,"",defaultBeanName);
        }

        if (Objects.isNull(ann)){
            return null;
        }

        injectBeanName = injectBeanName + ann.getSuffix();

        //寻找要注入的bean名称

        DependencyInjectionAnnotation newAnn = new DependencyInjectionAnnotation(
            ann.getQualifiedName(),
            ann.getShortName(),
            injectBeanName
        ) {};
        return newAnn;
    }

    private static class Builder extends DependencyInjectionAnnotation{
        private Builder(String qualifiedName, String shortName, String injectBeanName) {
            super(qualifiedName, shortName, injectBeanName);
        }
    }

    private static class Autowired extends DependencyInjectionAnnotation{
        private Autowired() {
            super("org.springframework.beans.factory.annotation.Autowired", "Autowired", null);
        }
    }

    private static class Resource extends DependencyInjectionAnnotation{
        private Resource() {
            super("javax.annotation.Resource", "Resource", null);
        }
    }

    private static class Qualifier extends DependencyInjectionAnnotation{
        private Qualifier() {
            super("org.springframework.beans.factory.annotation.Qualifier", "Qualifier", null);
        }
    }

    private static class ApacheDubboReference extends DependencyInjectionAnnotation{
        private ApacheDubboReference() {
            super("org.apache.dubbo.config.annotation.Reference", "Reference", null);
        }

        @Override
        protected String getSuffix() {
            return ":" + PsiUtils.getAnnotationAttributeValue(psiAnnotation,"version");
        }
    }

    private static class AlibabaDubboReference extends DependencyInjectionAnnotation{
        private AlibabaDubboReference() {
            super("com.alibaba.dubbo.config.annotation.Reference", "Reference", null);
        }

        @Override
        protected String getSuffix() {
            return ":" + PsiUtils.getAnnotationAttributeValue(psiAnnotation,"version");
        }
    }
}
